import numpy as np
import pandas as pd
import datetime as dt
from pandas_datareader import data as wb
import plotly.graph_objects as go
import matplotlib.pyplot as plt
import seaborn as sn
import yfinance as yf
%matplotlib inline
stocks = input().split()
asset = [stock.upper() + '.NS' for stock in stocks]
asset
#Example: SBIN HDFC ONGC WIPRO HEROMOTOCO LT ITC COALINDIA RELIANCE NCC
SBIN HDFC ONGC WIPRO HEROMOTOCO LT ITC COALINDIA RELIANCE NCC
['SBIN.NS', 'HDFC.NS', 'ONGC.NS', 'WIPRO.NS', 'HEROMOTOCO.NS', 'LT.NS', 'ITC.NS', 'COALINDIA.NS', 'RELIANCE.NS', 'NCC.NS']
asset.sort()
years = float(input('No. of year data you want to analyze: '))
## Example: 3 or 5 or 8 or 10
No. of year data you want to analyze: 5
endDate = dt.datetime.now()
startDate = endDate - dt.timedelta(days= 365 * years)
startDate
datetime.datetime(2018, 3, 31, 2, 2, 41, 607026)
yf.pdr_override()
pf_data = wb.get_data_yahoo(asset, start=startDate, end=endDate)['Adj Close']
[*********************100%***********************] 10 of 10 completed
pf_data
| COALINDIA.NS | HDFC.NS | HEROMOTOCO.NS | ITC.NS | LT.NS | NCC.NS | ONGC.NS | RELIANCE.NS | SBIN.NS | WIPRO.NS | |
|---|---|---|---|---|---|---|---|---|---|---|
| Date | ||||||||||
| 2018-04-02 | 177.256470 | 1715.386230 | 3040.504150 | 211.317444 | 1219.384155 | 109.640846 | 132.522751 | 865.632080 | 240.150375 | 212.622787 |
| 2018-04-03 | 178.182709 | 1703.860352 | 3039.628174 | 211.522034 | 1214.318481 | 116.553490 | 130.718475 | 872.030151 | 244.394363 | 208.401917 |
| 2018-04-04 | 175.372116 | 1682.955444 | 3058.141113 | 211.603867 | 1183.056885 | 115.042786 | 129.171951 | 867.522522 | 241.272354 | 206.713547 |
| 2018-04-05 | 177.448090 | 1702.693848 | 3154.043213 | 212.463043 | 1212.858154 | 118.567772 | 130.681671 | 880.415527 | 252.979858 | 210.126953 |
| 2018-04-06 | 176.170578 | 1706.940063 | 3151.791504 | 213.444962 | 1201.676880 | 119.529121 | 130.313446 | 883.130005 | 253.370132 | 208.438614 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 2023-03-23 | 213.350006 | 2569.850098 | 2362.500000 | 380.649994 | 2206.649902 | 105.949997 | 152.800003 | 2247.800049 | 512.750000 | 361.500000 |
| 2023-03-24 | 208.449997 | 2559.899902 | 2313.350098 | 378.700012 | 2166.149902 | 101.900002 | 149.399994 | 2203.300049 | 505.350006 | 361.750000 |
| 2023-03-27 | 208.399994 | 2561.899902 | 2308.600098 | 380.200012 | 2154.000000 | 101.449997 | 150.250000 | 2237.550049 | 510.149994 | 361.250000 |
| 2023-03-28 | 208.899994 | 2580.149902 | 2249.500000 | 379.750000 | 2133.600098 | 102.800003 | 147.199997 | 2248.000000 | 508.100006 | 356.200012 |
| 2023-03-29 | 212.949997 | 2603.050049 | 2304.149902 | 382.750000 | 2147.449951 | 106.849998 | 149.350006 | 2234.699951 | 516.500000 | 359.049988 |
1237 rows × 10 columns
(pf_data / pf_data.iloc[0] * 100).plot(figsize= (10,5))
plt.show()
# Importing Required Library
from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers import Dense, LSTM
## Scaling the data set as required
def Scale_data_set(data):
dataset = data.values
# Get the number of rows to train the model on
training_data_len = int(np.ceil( len(dataset) * .95 ))
scaler = MinMaxScaler(feature_range=(0,1))
scaled_data = scaler.fit_transform(dataset)
return training_data_len, scaled_data, dataset, scaler
## Creating a dataSet to be trained by LSTM
def Creating_training_data(training_data_len, scaled_data):
# Create the training data set
# Create the scaled training data set
train_data = scaled_data[0:int(training_data_len), :]
# Split the data into x_train and y_train data sets
x_train = []
y_train = []
for i in range(60, len(train_data)):
x_train.append(train_data[i-60:i, 0])
y_train.append(train_data[i, 0])
# Convert the x_train and y_train to numpy arrays
x_train, y_train = np.array(x_train), np.array(y_train)
# Reshape the data
x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1))
# x_train.shape
return x_train, y_train
## Training by LSTM
def LSTM_model(x_train, y_train):
# Build the LSTM model
model = Sequential()
model.add(LSTM(128, return_sequences=True, input_shape= (x_train.shape[1], 1)))
model.add(LSTM(64, return_sequences=False))
model.add(Dense(25))
model.add(Dense(1))
# Compile the model
model.compile(optimizer='adam', loss='mean_squared_error')
# Train the model
model.fit(x_train, y_train, batch_size=1, epochs=1)
return model
## Predicting data using the trained value
def miscellaneous(model, training_data_len, scaled_data, dataset, scaler):
# Create the testing data set
# Create a new array containing scaled values from index 1543 to 2002
test_data = scaled_data[training_data_len - 60: , :]
# Create the data sets x_test and y_test
x_test = []
y_test = dataset[training_data_len:, :]
for i in range(60, len(test_data)):
x_test.append(test_data[i-60:i, 0])
# Convert the data to a numpy array
x_test = np.array(x_test)
# Reshape the data
x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1], 1 ))
# Get the models predicted price values
predictions = model.predict(x_test)
predictions = scaler.inverse_transform(predictions)
# Get the root mean squared error (RMSE)
rmse = np.sqrt(np.mean(((predictions - y_test) ** 2)))
return predictions, rmse
## Ploting the chart with predicted values
def Ploting_Prediction(predictions ,training_data_len, data, title):
# Plot the data
train = data[:training_data_len]
valid = data[training_data_len:]
valid['Predictions'] = predictions
# Visualize the data
plt.figure(figsize=(16,6))
plt.title(title)
plt.xlabel('Date', fontsize=18)
plt.ylabel('Close Price in Rs', fontsize=18)
plt.plot(train['Close'])
plt.plot(valid[['Close', 'Predictions']])
plt.legend(['Train', 'Val', 'Predictions'], loc='lower right')
plt.show()
return train, valid
def plot_graph_plotly(predictions ,training_data_len, data, title):
# Plot the data
train = data[:training_data_len]
valid = data[training_data_len:]
valid['Predictions'] = predictions
#Max Sharpe Ratio
train_data = go.Scatter(
name='Training data',
x=data.index,
y=train['Close'],
marker=dict(color='blue',size=5,)
)
#Min Vol
Val_data = go.Scatter(
name='Actual Value',
x=valid.index,
y=valid['Close'],
marker=dict(color='green',size=5,)
)
#Random portfolio
Prediction_data = go.Scatter(
name='Predicted Data',
x=valid.index,
y=valid['Predictions'],
marker=dict(color='red',size=5,)
)
data = [train_data, Val_data, Prediction_data]
layout = go.Layout(
title = title,
yaxis = dict(title='Close Price in Rs'),
xaxis = dict(title='Date'),
showlegend = True,
legend = dict(
x = .83, y = 0, traceorder='normal',
bgcolor='#E2E2E2',
bordercolor='black',
borderwidth=2),
width=980,
height=500)
fig = go.Figure(data=data, layout=layout)
fig.show()
return train, valid
## Compiling all functions to one functions
def Stock_prediction(data, title):
training_data_len, scaled_data, dataset, scaler = Scale_data_set(data)
x_train, y_train = Creating_training_data(training_data_len, scaled_data)
model = LSTM_model(x_train, y_train)
predictions, rmse = miscellaneous(model, training_data_len, scaled_data, dataset, scaler)
train, valid = plot_graph_plotly(predictions ,training_data_len, data, title)
return train, valid, rmse, predictions
data = {}
for st in asset:
data['{}'.format(st)] = pf_data.filter([st])
pf_data
| COALINDIA.NS | HDFC.NS | HEROMOTOCO.NS | ITC.NS | LT.NS | NCC.NS | ONGC.NS | RELIANCE.NS | SBIN.NS | WIPRO.NS | |
|---|---|---|---|---|---|---|---|---|---|---|
| Date | ||||||||||
| 2018-04-02 | 177.256470 | 1715.386230 | 3040.504150 | 211.317444 | 1219.384155 | 109.640846 | 132.522751 | 865.632080 | 240.150375 | 212.622787 |
| 2018-04-03 | 178.182709 | 1703.860352 | 3039.628174 | 211.522034 | 1214.318481 | 116.553490 | 130.718475 | 872.030151 | 244.394363 | 208.401917 |
| 2018-04-04 | 175.372116 | 1682.955444 | 3058.141113 | 211.603867 | 1183.056885 | 115.042786 | 129.171951 | 867.522522 | 241.272354 | 206.713547 |
| 2018-04-05 | 177.448090 | 1702.693848 | 3154.043213 | 212.463043 | 1212.858154 | 118.567772 | 130.681671 | 880.415527 | 252.979858 | 210.126953 |
| 2018-04-06 | 176.170578 | 1706.940063 | 3151.791504 | 213.444962 | 1201.676880 | 119.529121 | 130.313446 | 883.130005 | 253.370132 | 208.438614 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 2023-03-23 | 213.350006 | 2569.850098 | 2362.500000 | 380.649994 | 2206.649902 | 105.949997 | 152.800003 | 2247.800049 | 512.750000 | 361.500000 |
| 2023-03-24 | 208.449997 | 2559.899902 | 2313.350098 | 378.700012 | 2166.149902 | 101.900002 | 149.399994 | 2203.300049 | 505.350006 | 361.750000 |
| 2023-03-27 | 208.399994 | 2561.899902 | 2308.600098 | 380.200012 | 2154.000000 | 101.449997 | 150.250000 | 2237.550049 | 510.149994 | 361.250000 |
| 2023-03-28 | 208.899994 | 2580.149902 | 2249.500000 | 379.750000 | 2133.600098 | 102.800003 | 147.199997 | 2248.000000 | 508.100006 | 356.200012 |
| 2023-03-29 | 212.949997 | 2603.050049 | 2304.149902 | 382.750000 | 2147.449951 | 106.849998 | 149.350006 | 2234.699951 | 516.500000 | 359.049988 |
1237 rows × 10 columns
for i in asset:
DATA = data[i]
DATA = DATA.rename(columns = {i:"Close"})
train, valid, rmse, predictions = Stock_prediction(DATA, i)
print("'root mean squared error' of {} = ".format(i) + str(rmse))
1116/1116 [==============================] - 31s 25ms/step - loss: 0.0023 2/2 [==============================] - 1s 33ms/step
C:\Users\DC\AppData\Local\Temp/ipykernel_8728/3901712836.py:24: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy valid['Predictions'] = predictions
'root mean squared error' of COALINDIA.NS = 10.86642588586606 1116/1116 [==============================] - 32s 26ms/step - loss: 0.0038 2/2 [==============================] - 1s 31ms/step
C:\Users\DC\AppData\Local\Temp/ipykernel_8728/3901712836.py:24: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
'root mean squared error' of HDFC.NS = 76.52052309278811 1116/1116 [==============================] - 35s 28ms/step - loss: 0.0048 2/2 [==============================] - 1s 38ms/step
C:\Users\DC\AppData\Local\Temp/ipykernel_8728/3901712836.py:24: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
'root mean squared error' of HEROMOTOCO.NS = 58.43621901908743 1116/1116 [==============================] - 34s 27ms/step - loss: 0.0015 2/2 [==============================] - 1s 42ms/step
C:\Users\DC\AppData\Local\Temp/ipykernel_8728/3901712836.py:24: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
'root mean squared error' of ITC.NS = 21.208195699140397 1116/1116 [==============================] - 32s 25ms/step - loss: 0.0021 WARNING:tensorflow:5 out of the last 9 calls to <function Model.make_predict_function.<locals>.predict_function at 0x000001E736B903A0> triggered tf.function retracing. Tracing is expensive and the excessive number of tracings could be due to (1) creating @tf.function repeatedly in a loop, (2) passing tensors with different shapes, (3) passing Python objects instead of tensors. For (1), please define your @tf.function outside of the loop. For (2), @tf.function has reduce_retracing=True option that can avoid unnecessary retracing. For (3), please refer to https://www.tensorflow.org/guide/function#controlling_retracing and https://www.tensorflow.org/api_docs/python/tf/function for more details. 2/2 [==============================] - 1s 82ms/step
C:\Users\DC\AppData\Local\Temp/ipykernel_8728/3901712836.py:24: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
'root mean squared error' of LT.NS = 70.98902559976307 1116/1116 [==============================] - 35s 28ms/step - loss: 0.0040 WARNING:tensorflow:6 out of the last 11 calls to <function Model.make_predict_function.<locals>.predict_function at 0x000001E727F32F70> triggered tf.function retracing. Tracing is expensive and the excessive number of tracings could be due to (1) creating @tf.function repeatedly in a loop, (2) passing tensors with different shapes, (3) passing Python objects instead of tensors. For (1), please define your @tf.function outside of the loop. For (2), @tf.function has reduce_retracing=True option that can avoid unnecessary retracing. For (3), please refer to https://www.tensorflow.org/guide/function#controlling_retracing and https://www.tensorflow.org/api_docs/python/tf/function for more details. 2/2 [==============================] - 2s 66ms/step
C:\Users\DC\AppData\Local\Temp/ipykernel_8728/3901712836.py:24: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
'root mean squared error' of NCC.NS = 8.534030910737915 1116/1116 [==============================] - 37s 28ms/step - loss: 0.0032 2/2 [==============================] - 1s 42ms/step
C:\Users\DC\AppData\Local\Temp/ipykernel_8728/3901712836.py:24: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
'root mean squared error' of ONGC.NS = 3.3737945518310957 1116/1116 [==============================] - 32s 26ms/step - loss: 0.0040 2/2 [==============================] - 1s 47ms/step
C:\Users\DC\AppData\Local\Temp/ipykernel_8728/3901712836.py:24: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
'root mean squared error' of RELIANCE.NS = 70.51329251191241 1116/1116 [==============================] - 30s 24ms/step - loss: 0.0027 2/2 [==============================] - 1s 39ms/step
C:\Users\DC\AppData\Local\Temp/ipykernel_8728/3901712836.py:24: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
'root mean squared error' of SBIN.NS = 23.589943156963116 1116/1116 [==============================] - 37s 30ms/step - loss: 0.0024 2/2 [==============================] - 1s 49ms/step
C:\Users\DC\AppData\Local\Temp/ipykernel_8728/3901712836.py:24: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
'root mean squared error' of WIPRO.NS = 14.433297000160131
retrn = (pf_data / pf_data.shift(1)) - 1
retrn
| COALINDIA.NS | HDFC.NS | HEROMOTOCO.NS | ITC.NS | LT.NS | NCC.NS | ONGC.NS | RELIANCE.NS | SBIN.NS | WIPRO.NS | |
|---|---|---|---|---|---|---|---|---|---|---|
| Date | ||||||||||
| 2018-04-02 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 2018-04-03 | 0.005225 | -0.006719 | -0.000288 | 0.000968 | -0.004154 | 0.063048 | -0.013615 | 0.007391 | 0.017672 | -0.019851 |
| 2018-04-04 | -0.015774 | -0.012269 | 0.006091 | 0.000387 | -0.025744 | -0.012961 | -0.011831 | -0.005169 | -0.012774 | -0.008102 |
| 2018-04-05 | 0.011838 | 0.011728 | 0.031360 | 0.004060 | 0.025190 | 0.030641 | 0.011688 | 0.014862 | 0.048524 | 0.016513 |
| 2018-04-06 | -0.007199 | 0.002494 | -0.000714 | 0.004622 | -0.009219 | 0.008108 | -0.002818 | 0.003083 | 0.001543 | -0.008035 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 2023-03-23 | -0.002804 | -0.005553 | 0.003952 | 0.007677 | -0.003297 | 0.010009 | 0.008248 | -0.012650 | -0.016873 | -0.013373 |
| 2023-03-24 | -0.022967 | -0.003872 | -0.020804 | -0.005123 | -0.018354 | -0.038226 | -0.022251 | -0.019797 | -0.014432 | 0.000692 |
| 2023-03-27 | -0.000240 | 0.000781 | -0.002053 | 0.003961 | -0.005609 | -0.004416 | 0.005689 | 0.015545 | 0.009498 | -0.001382 |
| 2023-03-28 | 0.002399 | 0.007124 | -0.025600 | -0.001184 | -0.009471 | 0.013307 | -0.020300 | 0.004670 | -0.004018 | -0.013979 |
| 2023-03-29 | 0.019387 | 0.008876 | 0.024294 | 0.007900 | 0.006491 | 0.039397 | 0.014606 | -0.005916 | 0.016532 | 0.008001 |
1237 rows × 10 columns
annual_returns = retrn.mean() * 250 *100
annual_returns.values[::-1].sort()
annual_returns
COALINDIA.NS 24.134615 HDFC.NS 21.721732 HEROMOTOCO.NS 15.547064 ITC.NS 15.474683 LT.NS 14.570013 NCC.NS 13.656731 ONGC.NS 13.356305 RELIANCE.NS 9.747047 SBIN.NS 8.729765 WIPRO.NS -0.707604 dtype: float64
sorted_annual_return = annual_returns[0:5]
sorted_annual_return
COALINDIA.NS 24.134615 HDFC.NS 21.721732 HEROMOTOCO.NS 15.547064 ITC.NS 15.474683 LT.NS 14.570013 dtype: float64
assets = list(sorted_annual_return.index)
assets
['COALINDIA.NS', 'HDFC.NS', 'HEROMOTOCO.NS', 'ITC.NS', 'LT.NS']
pf_data = pf_data.filter(assets)
pf_data
| COALINDIA.NS | HDFC.NS | HEROMOTOCO.NS | ITC.NS | LT.NS | |
|---|---|---|---|---|---|
| Date | |||||
| 2018-04-02 | 177.256470 | 1715.386230 | 3040.504150 | 211.317444 | 1219.384155 |
| 2018-04-03 | 178.182709 | 1703.860352 | 3039.628174 | 211.522034 | 1214.318481 |
| 2018-04-04 | 175.372116 | 1682.955444 | 3058.141113 | 211.603867 | 1183.056885 |
| 2018-04-05 | 177.448090 | 1702.693848 | 3154.043213 | 212.463043 | 1212.858154 |
| 2018-04-06 | 176.170578 | 1706.940063 | 3151.791504 | 213.444962 | 1201.676880 |
| ... | ... | ... | ... | ... | ... |
| 2023-03-23 | 213.350006 | 2569.850098 | 2362.500000 | 380.649994 | 2206.649902 |
| 2023-03-24 | 208.449997 | 2559.899902 | 2313.350098 | 378.700012 | 2166.149902 |
| 2023-03-27 | 208.399994 | 2561.899902 | 2308.600098 | 380.200012 | 2154.000000 |
| 2023-03-28 | 208.899994 | 2580.149902 | 2249.500000 | 379.750000 | 2133.600098 |
| 2023-03-29 | 212.949997 | 2603.050049 | 2304.149902 | 382.750000 | 2147.449951 |
1237 rows × 5 columns
returns = retrn.filter(assets)
returns
| COALINDIA.NS | HDFC.NS | HEROMOTOCO.NS | ITC.NS | LT.NS | |
|---|---|---|---|---|---|
| Date | |||||
| 2018-04-02 | NaN | NaN | NaN | NaN | NaN |
| 2018-04-03 | 0.005225 | -0.006719 | -0.000288 | 0.000968 | -0.004154 |
| 2018-04-04 | -0.015774 | -0.012269 | 0.006091 | 0.000387 | -0.025744 |
| 2018-04-05 | 0.011838 | 0.011728 | 0.031360 | 0.004060 | 0.025190 |
| 2018-04-06 | -0.007199 | 0.002494 | -0.000714 | 0.004622 | -0.009219 |
| ... | ... | ... | ... | ... | ... |
| 2023-03-23 | -0.002804 | -0.005553 | 0.003952 | 0.007677 | -0.003297 |
| 2023-03-24 | -0.022967 | -0.003872 | -0.020804 | -0.005123 | -0.018354 |
| 2023-03-27 | -0.000240 | 0.000781 | -0.002053 | 0.003961 | -0.005609 |
| 2023-03-28 | 0.002399 | 0.007124 | -0.025600 | -0.001184 | -0.009471 |
| 2023-03-29 | 0.019387 | 0.008876 | 0.024294 | 0.007900 | 0.006491 |
1237 rows × 5 columns
num_assets = len(assets)
num_assets
5
weights = np.random.random(num_assets)
weights /= np.sum(weights)
weights
array([0.2311764 , 0.24094695, 0.19052129, 0.1108554 , 0.22649996])
np.sum(weights * returns.mean()) * 250
0.10329953963472441
np.dot(weights.T, np.dot(returns.cov() * 250, weights))
0.045029652378750305
np.sqrt(np.dot(weights.T,np.dot(returns.cov() * 250, weights)))
0.21220191417315326
corr_matrix = returns.corr()
corr_matrix
| COALINDIA.NS | HDFC.NS | HEROMOTOCO.NS | ITC.NS | LT.NS | |
|---|---|---|---|---|---|
| COALINDIA.NS | 1.000000 | 0.231154 | 0.274088 | 0.300004 | 0.344331 |
| HDFC.NS | 0.231154 | 1.000000 | 0.380305 | 0.381712 | 0.546168 |
| HEROMOTOCO.NS | 0.274088 | 0.380305 | 1.000000 | 0.278446 | 0.402051 |
| ITC.NS | 0.300004 | 0.381712 | 0.278446 | 1.000000 | 0.372967 |
| LT.NS | 0.344331 | 0.546168 | 0.402051 | 0.372967 | 1.000000 |
pfolio_returns = []
pfolio_volatilities = []
pfolio_weights = []
for x in range (5000):
weights = np.random.random(num_assets)
weights /= np.sum(weights)
pfolio_returns.append(np.sum(weights * returns.mean()) * 250)
pfolio_volatilities.append(np.sqrt(np.dot(weights.T,np.dot(returns.cov() * 250, weights))))
pfolio_weights.append(weights)
pfolio_returns = np.array(pfolio_returns)
pfolio_volatilities = np.array(pfolio_volatilities)
#pfolio_weights = pfolio_weights.tolist()
# pfolio_returns, pfolio_volatilities, pfolio_weights
portfolios = pd.DataFrame({'Return': pfolio_returns, 'Volatility': pfolio_volatilities})
portfolios.plot(x='Volatility', y='Return', kind='scatter', figsize=(10, 6));
plt.xlabel('Expected Volatility')
plt.ylabel('Expected Return')
plt.show()
max_return = max(pfolio_returns)
max_return
0.15181206184284307
max_rindex = np.where(pfolio_returns == max_return)
print(max_rindex)
(array([2754], dtype=int64),)
max_rvolatility = pfolio_volatilities[max_rindex[0][0]]
max_rvolatility
0.22375353322206148
max_rweights = pfolio_weights[max_rindex[0][0]]
max_rweights
array([0.01906369, 0.05031982, 0.00552441, 0.42967666, 0.49541542])
min_volatility = pfolio_volatilities.min()
min_volatility
0.2032442633026616
min_vindex = np.where(pfolio_volatilities == min_volatility)
min_vindex
(array([3964], dtype=int64),)
min_vreturns = pfolio_returns[min_vindex[0][0]]
min_vreturns
0.10898203038264713
min_vweights = pfolio_weights[min_vindex[0][0]]
min_vweights
array([0.20377067, 0.09930902, 0.18635316, 0.33062592, 0.17994123])
max_sr = []
max_sr = [str(round(max_return * 100,3) ) + '%', str(round(max_rvolatility * 100,3)) + '%']
for i in range(num_assets):
max_sr.append(str(round(max_rweights[i] * 100,3)) + '%')
max_sr
['15.181%', '22.375%', '1.906%', '5.032%', '0.552%', '42.968%', '49.542%']
min_vol = []
min_vol = [str(round(min_vreturns*100,3)) + '%', str(round(min_volatility * 100,3)) + '%']
for i in range(num_assets):
min_vol.append(str(round(min_vweights[i] *100,3)) + '%')
min_vol
['10.898%', '20.324%', '20.377%', '9.931%', '18.635%', '33.063%', '17.994%']
#Max Sharpe Ratio
MaxSharpeRatio = go.Scatter(
name='Maximium Return',
mode='markers',
x=[max_rvolatility],
y=[max_return],
marker=dict(color='red',size=14,line=dict(width=3, color='black'))
)
#Min Vol
MinVol = go.Scatter(
name='Mininium Risk',
mode='markers',
x=[min_volatility],
y=[min_vreturns],
marker=dict(color='green',size=14,line=dict(width=3, color='black'))
)
#Random portfolio
EF_curve = go.Scatter(
name='Random Portfolios',
mode='markers',
x= pfolio_volatilities,
y= pfolio_returns,
marker=dict(color='blue',size=5)
)
data = [MaxSharpeRatio, MinVol, EF_curve]
layout = go.Layout(
title = 'Portfolio Optimisation with the MPT',
yaxis = dict(title='Annualised Return'),
xaxis = dict(title='Annualised Volatility'),
showlegend = True,
legend = dict(
x = .75, y = 0, traceorder='normal',
bgcolor='#E2E2E2',
bordercolor='black',
borderwidth=2),
width=800,
height=600)
fig = go.Figure(data=data, layout=layout)
fig.show()
col = []
col = ['Returns', 'Volatility']
for i in range(num_assets):
col.append(pf_data.columns[i])
result_table = pd.DataFrame(columns = [col], index=['maximum Return', 'minimun risk'])
result_table.iloc[0] = max_sr
result_table.iloc[1] = min_vol
result_table
| Returns | Volatility | COALINDIA.NS | HDFC.NS | HEROMOTOCO.NS | ITC.NS | LT.NS | |
|---|---|---|---|---|---|---|---|
| maximum Return | 15.181% | 22.375% | 1.906% | 5.032% | 0.552% | 42.968% | 49.542% |
| minimun risk | 10.898% | 20.324% | 20.377% | 9.931% | 18.635% | 33.063% | 17.994% |
sn.heatmap(corr_matrix, annot=True)
plt.show()
trace = go.Heatmap(
x = assets,
y = assets,
z = corr_matrix,
type = 'heatmap',
colorscale = 'Viridis',
hovertemplate = "%{z}"
)
layout = go.Layout(
title = 'Correlation',
yaxis = dict(title='Stocks'),
xaxis = dict(title='Stocks'),
showlegend = False,
width=500,
height=500)
data = [trace]
fig = go.Figure(data = data, layout = layout)
fig.show()